package xing.appwidget.main

import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.schedulers.Schedulers
import xing.appwidget.R
import xing.appwidget.bean.ApplicationItem
import xing.appwidget.databinding.ItemMainAppInfoBinding


class AppListAdapter() : RecyclerView.Adapter<ViewHolder>() {

    companion object {
        private const val TAG = "AppListAdapter"
    }

    private val appList = ArrayList<ApplicationItem>()

    fun setAppList(apps: List<ApplicationItem>) {
        val diff = DiffUtil.calculateDiff(ViewHolder.DiffUtilCallback(ArrayList(appList), apps))
        appList.clear()
        appList.addAll(apps)
        diff.dispatchUpdatesTo(this)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
                ItemMainAppInfoBinding.inflate(
                        LayoutInflater.from(parent.context),
                        parent,
                        false
                )
        )
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bindData(appList[position])
    }

    override fun getItemCount(): Int {
        return appList.size
    }
}

class ViewHolder(private val binding: ItemMainAppInfoBinding) :
        RecyclerView.ViewHolder(binding.root) {

    companion object {
        private const val TAG = "AppListAdapter"
    }

    private var disposable: Disposable? = null

    init {
        val childCount = binding.root.childCount
        for (x in 0 until childCount) {
            val child = binding.root.getChildAt(x)
            child.setOnLongClickListener {
                if (it !is TextView) {
                    return@setOnLongClickListener false
                }
                val cm = it.context.getSystemService(Context.CLIPBOARD_SERVICE)
                        as ClipboardManager
                val text = it.text.toString()
                val clipData: ClipData = ClipData.newPlainText(null, text)
                cm.setPrimaryClip(clipData)
                Toast.makeText(it.context, "已复制 $text", Toast.LENGTH_SHORT).show()
                return@setOnLongClickListener true
            }
            child.setOnClickListener { itemView.performClick() }
        }
    }

    fun bindData(item: ApplicationItem) {
        loadIcon(item)
        binding.tvName.text = item.label
        binding.tvName.isSelected = true
        binding.tvPackageName.text = item.packageName
        binding.tvVersion.text = item.versionName
        binding.tvTargetSdk.text = itemView.context.getString(R.string.sdk_level, item.sdk)
        binding.tvUid.text = itemView.context.getString(R.string.app_uid, item.uid)
//        itemView.setOnClickListener { AppDetailActivity.start(it.context, item.packageName, item.label ?: "") }
    }

    private fun loadIcon(item: ApplicationItem) {
        if (disposable?.isDisposed == false) {
            disposable?.dispose()
        }
        binding.ivIcon.visibility = View.INVISIBLE
        disposable = Observable.just(item)
                .map { appItem ->
                    return@map appItem.loadIcon(binding.root.context.packageManager)
                }
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                        { icon ->
                            binding.ivIcon.setImageDrawable(icon)
                            binding.ivIcon.visibility = View.VISIBLE
                        },
                        { throwable -> Log.e(TAG, "bindData: ", throwable) })
    }

    class DiffUtilCallback(val oldList: List<ApplicationItem>?, val newList: List<ApplicationItem>?) : DiffUtil.Callback() {

        override fun getOldListSize() = oldList?.size ?: 0

        override fun getNewListSize() = newList?.size ?: 0

        override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
            val old = oldList?.getOrNull(oldItemPosition)
            val new = newList?.getOrNull(newItemPosition)
            return old?.packageName == new?.packageName && old?.enabled == new?.enabled
        }

        override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int) = true

    }
}